from core.exprs import Literal, Application, Variable, Body, Define, IF, Operator, DefineFunction, DefineVar


class ASTPrinter:
    def print(self, ast):
        format_str = self.format(ast)
        print(format_str)

    def format(self, ast):
        if isinstance(ast, Literal):
            if isinstance(ast.value, str):
                return '"' + ast.value + '"'
            return str(ast.value)
        if isinstance(ast, Variable):
            return str(ast.name.value)
        elif isinstance(ast, Application):
            output = "("
            output += self.format(ast.first)
            output += " "
            for i, arg in enumerate(ast.sequences):
                output += self.format(arg)
                if i < len(ast.sequences) - 1:
                    output += " "
            output += ")"
            return output
        elif isinstance(ast, Body):
            # output = "("
            output = ""
            for i, define in enumerate(ast.defines):
                output += self.format(define)
                if i < len(ast.defines) - 1:
                    output += " "
            for i, expr in enumerate(ast.expressions):
                output += self.format(expr)
                if i < len(ast.expressions) - 1:
                    output += " "
            # output += ")"
            return output
        # elif isinstance(ast, Define):
        #     output = "(define "
        #     if len(ast.arguments) > 1:
        #         output += "("
        #     for i, arg in enumerate(ast.arguments):
        #         output += self.format(arg)
        #         if i < len(ast.arguments) - 1:
        #             output += " "
        #     if len(ast.arguments) > 1:
        #         output += ")"
        #     output += "\n    "
        #     output += self.format(ast.body)
        #     output += ")"
        #     return output
        elif isinstance(ast, Operator):
            output = ast.operator.value
            return output
        elif isinstance(ast, IF):
            output = "(if "
            output += self.format(ast.condition)
            output += " "
            output += self.format(ast.consequence)
            if ast.alternative is not None:
                output += " "
                output += self.format(ast.alternative)
            output += ")"
            return output
        elif isinstance(ast, DefineFunction):
            output = "(define-function "
            output += "("
            output += ast.name.value
            for i, arg in enumerate(ast.arguments):
                output += " "
                if i < len(ast.arguments):
                    output += " "
                    output += self.format(ast.arguments[i])
                    i += 1
            output += ")"
            output += self.format(ast.body)
            output += ")"
            return output
        elif isinstance(ast, DefineVar):
            output = "(define-var "
            output += ast.name.value
            output += " "
            output += self.format(ast.value)
            output += ")"
            return output